package design.patterns.creation;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 单例模式
 * 解释：
 * 单例模式是一种创建型设计模式， 让你能够保证一个类只有一个实例，
 * 并提供一个访问该实例的全局节点。
 */

/**
 * 情景
 * 一个类只能创建一个实例
 */
public class E_Singleton {
    public static void main(String[] args) throws InterruptedException {
        /* 单线程-简单单例 */
        System.out.println("====单线程-简单单例====value相同");
        SimpleSingleton getInstance = SimpleSingleton.getInstance("getInstance");
        System.out.println(getInstance);

        SimpleSingleton getInstance1 = SimpleSingleton.getInstance("getInstance1");
        System.out.println(getInstance1);


        SimpleSingleton.resetInstance();

        /* 多线程-简单单例 */
        System.out.println("====多线程-简单单例====value不同");

        CountDownLatch simpleSingleton_latch = new CountDownLatch(2);
        new Thread(()->{//线程1
            SimpleSingleton thread1 = SimpleSingleton.getInstance("thread1");
            System.out.println(thread1);
            simpleSingleton_latch.countDown();
        }).start();
        Thread.sleep(500);
        new Thread(()->{//线程2
            SimpleSingleton thread2 = SimpleSingleton.getInstance("thread2");
            System.out.println(thread2);
            simpleSingleton_latch.countDown();
        }).start();

        simpleSingleton_latch.await();
        /* 多线程-延迟加载单例 */
        CountDownLatch delayedLoadingSingleton_latch = new CountDownLatch(2);
        System.out.println("====多线程-简单单例====value相同");
        new Thread(()->{//线程1
            DelayedLoadingSingleton thread1 = DelayedLoadingSingleton.getInstance("thread1-DelayedLoadingSingleton");
            System.out.println(thread1);
            delayedLoadingSingleton_latch.countDown();
        }).start();
        new Thread(()->{//线程2
            DelayedLoadingSingleton thread2 = DelayedLoadingSingleton.getInstance("thread2-DelayedLoadingSingleton");
            System.out.println(thread2);
            delayedLoadingSingleton_latch.countDown();
        }).start();

        delayedLoadingSingleton_latch.await();
    }
}

final class SimpleSingleton{
    private static SimpleSingleton instance;
    private String value;
    private static AtomicInteger count =new AtomicInteger(0);

    private SimpleSingleton(String value) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        count.incrementAndGet();
        this.value = value;
    }
    public static SimpleSingleton getInstance(String value){
        if (instance == null){
            instance = new SimpleSingleton(value);
            System.out.println("实例为空，创建实例");
        }
        return instance;
    }
    public static void resetInstance() {
        instance = null;
    }

    @Override
    public String toString() {
        return "SimpleSingleton{" +
                "value='" + value + " count="+count+'\'' +
                '}';
    }
}
final class DelayedLoadingSingleton{
    private static volatile DelayedLoadingSingleton instance;
    private String value;
    public static AtomicInteger count = new AtomicInteger(0);
    private DelayedLoadingSingleton(String value) {
        this.value = value;
    }

    public static DelayedLoadingSingleton getInstance(String value){
        if (instance!=null){
            return instance;
        }
        synchronized (DelayedLoadingSingleton.class){
            if (instance==null){
                count.incrementAndGet();
                System.out.println("实例为空，创建实例");
                instance = new DelayedLoadingSingleton(value);
            }
            return instance;
        }

    }

    @Override
    public String toString() {
        return "DelayedLoadingSingleton{" +
                "value='" + value + " count="+count+'\'' +
                '}';
    }
}
